package com.zhu.instructions.references;

import com.zhu.instructions.base.Index16Instruction;
import com.zhu.rtda.Frame;
import com.zhu.rtda.InstanceOop;
import com.zhu.rtda.OperandStack;
import com.zhu.rtda.heap.InstanceKlass;
import com.zhu.rtda.heap.constant.ClassRef;
import com.zhu.rtda.heap.constant.RuntimeConstantPool;
/**
 * CHECKCAST 指令：检查对象是否可以转换为指定类型，若不能则抛出 ClassCastException。
 *
 * <p>字节码格式：checkcast indexbyte1 indexbyte2 (opcode 0xC0)
 *
 * <p>执行逻辑：
 * <ul>
 *   <li>从操作数栈弹出对象引用（ref）</li>
 *   <li>若 ref 为 null，直接通过（null 可转任意引用类型）</li>
 *   <li>否则，解析目标类，并检查 ref 的类型是否兼容</li>
 *   <li>若不兼容，抛出 ClassCastException</li>
 *   <li>无论是否检查，都将原引用重新压回栈（指令不改变栈内容，仅做验证）</li>
 * </ul>
 */
public class CHECK_CAST extends Index16Instruction {

    @Override
    public void execute(Frame frame) {
        // 1. 弹出对象引用（稍后要压回去）
        OperandStack stack = frame.getOperandStack();
        InstanceOop ref = stack.popRef();

        // 2. null 引用总是可以通过类型检查
        if (ref != null) {
            // 3. 解析目标类
            InstanceKlass currentClass = frame.getMethod().getClazz();
            RuntimeConstantPool cp = currentClass.getConstantPool();
            ClassRef classRef = (ClassRef) cp.getConstant(this.index);
            InstanceKlass targetClass = classRef.resolvedKlass();

            // 4. 检查类型兼容性
            InstanceKlass refClass = ref.getKlass();
            if (!targetClass.isAssignableFrom(refClass)) {
                throw new ClassCastException();
            }
        }

        // 5. 重新压回原引用（CHECKCAST 不改变栈内容）
        stack.pushRef(ref);
    }
}
